﻿using Mall.Repository.Repository;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;

namespace Mall.Repository.RepositoryProgram
{
    internal class MethodCallExpressionToSql : BaseExpressionToSql<MethodCallExpression>
    {
        private static Dictionary<string, Action<MethodCallExpression, SqlBuilder>> _Methods = new Dictionary<string, Action<MethodCallExpression, SqlBuilder>>
    {
        { "Like", Like },
        { "LikeLeft", LikeLeft },
        { "LikeRight", LikeRight },
        { "In", InnerIn }
    };

        private static void InnerIn(MethodCallExpression expression, SqlBuilder sqlBuilder)
        {
            ExpressionToSqlProvider.Where(expression.Arguments[0], sqlBuilder);
            sqlBuilder += " in";
            ExpressionToSqlProvider.In(expression.Arguments[1], sqlBuilder);
        }

        private static void Like(MethodCallExpression expression, SqlBuilder sqlBuilder)
        {
            if (expression.Object != null)
            {
                ExpressionToSqlProvider.Where(expression.Object, sqlBuilder);
            }

            ExpressionToSqlProvider.Where(expression.Arguments[0], sqlBuilder);
            sqlBuilder += " like concat('%',";
            ExpressionToSqlProvider.Where(expression.Arguments[1], sqlBuilder);
            sqlBuilder += ",'%') ";
        }

        private static void LikeLeft(MethodCallExpression expression, SqlBuilder sqlBuilder)
        {
            if (expression.Object != null)
            {
                ExpressionToSqlProvider.Where(expression.Object, sqlBuilder);
            }

            ExpressionToSqlProvider.Where(expression.Arguments[0], sqlBuilder);
            sqlBuilder += " like concat('%',";
            ExpressionToSqlProvider.Where(expression.Arguments[1], sqlBuilder);
            sqlBuilder += ") ";
        }

        private static void LikeRight(MethodCallExpression expression, SqlBuilder sqlBuilder)
        {
            if (expression.Object != null)
            {
                ExpressionToSqlProvider.Where(expression.Object, sqlBuilder);
            }

            ExpressionToSqlProvider.Where(expression.Arguments[0], sqlBuilder);
            sqlBuilder += " like concat(";
            ExpressionToSqlProvider.Where(expression.Arguments[1], sqlBuilder);
            sqlBuilder += ",'%') ";
        }

        protected override SqlBuilder Where(MethodCallExpression expression, SqlBuilder sqlBuilder)
        {
            MethodInfo methodInfo = expression.Method;
            if (methodInfo.IsGenericMethod)
            {
                methodInfo = methodInfo.GetGenericMethodDefinition();
            }

            if (_Methods.TryGetValue(methodInfo.Name, out var value))
            {
                value(expression, sqlBuilder);
                return sqlBuilder;
            }

            throw new NotImplementedException("Unimplemented method:" + expression.Method);
        }
    }
}
